package com.sparrow.common.thread.executor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.LinkedBlockingQueue;

public class SingleThreadExecutor extends Thread {

	private Logger logger = LoggerFactory.getLogger(SingleThreadExecutor.class);

	// 命令执行队列
	protected LinkedBlockingQueue<Runnable> command_queue = new LinkedBlockingQueue<>();
	// 线程名称
	protected String threadName;
	// 运行标志
	private volatile boolean stop;

	private boolean processingCompleted = false;

	public SingleThreadExecutor(ThreadGroup group, String threadName, int heart) {
		super(group, threadName);
		this.threadName = threadName;
		this.setUncaughtExceptionHandler((t, e) -> {
			command_queue.clear();
		});
	}

	public SingleThreadExecutor(String threadName, int heart) {
		this(new ThreadGroup(threadName), threadName, heart);
	}

	@Override
    public void run() {
		stop = false;
		int loop = 0;
		while (!stop) {
			Runnable command = command_queue.poll();
			if (command == null) {
				try {
					synchronized (this) {
						loop = 0;
						processingCompleted = true;
						wait();
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			} else {
				try {
					loop++;
					processingCompleted = false;
					command.run();
					if (loop > 1000) {
						loop = 0;
						try {
							Thread.sleep(1);
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				} catch (Exception e) {
					logger.error("run error", e);
				}
			}
		}
	}

	public void stop(boolean flag) {
		stop = flag;
		this.command_queue.clear();
		try {
			synchronized (this) {
				if (processingCompleted) {
					processingCompleted = false;
					notify();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void addCommand(Runnable command) {
		try {
			this.command_queue.add(command);
			synchronized (this) {
				notify();
			}
		} catch (Exception e) {
			logger.error("addCommand error", e);
		}
	}


}
